#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "tag.h"
#include "tlv.h"
#include "message.h"

void printf_hex(char *pcPrefix, unsigned char *pucData, int iLen)
{
	int i=0;

	if(NULL != pcPrefix){
		printf("%s", pcPrefix);
	}
	for(i=0; i<iLen; i++){
		printf("%02X", pucData[i]);
	}
	printf("\n");
}

int pack_module_info_message(Message *pstMsg)
{
	int len = 0;
	unsigned short usDLen = 0;
	unsigned char *ptr = pstMsg->aucMsgData;
	unsigned char aucTag[2] = {0};
	
	pstMsg->usMsgLen = 0;
	
	ptr += MSG_HEAD_LEN_SZ;
	
	aucTag[0] = TAG_MODULE;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucModule, strlen((char *)pstMsg->aucModule));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_MODULE_VER;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucModuleVer, strlen((char *)pstMsg->aucModuleVer));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_IMEI;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucIMEI, strlen((char *)pstMsg->aucIMEI));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	if(0 != pstMsg->aucLBS[0]){
		aucTag[0] = TAG_LBS;
		len = pack_tlv_data(ptr, aucTag, pstMsg->aucLBS, strlen((char *)pstMsg->aucLBS));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	aucTag[0] = TAG_NET_TYPER;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->acNetType, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	
	pstMsg->aucMsgData[0] = usDLen>>8;
	pstMsg->aucMsgData[1] = usDLen&0xFF;
	
	pstMsg->usMsgLen = usDLen+MSG_HEAD_LEN_SZ;
	return pstMsg->usMsgLen;
}

int pack_senser_info_message(Message *pstMsg)
{
	int len = 0;
	unsigned short usDLen = 0;
	unsigned char *ptr = pstMsg->aucMsgData;
	unsigned char aucTag[2] = {0};
	
	pstMsg->usMsgLen = 0;
	
	ptr += MSG_HEAD_LEN_SZ;
	
	aucTag[0] = TAG_IMEI;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucIMEI, strlen((char *)pstMsg->aucIMEI));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	if(0 != pstMsg->aucLBS[0]){
		aucTag[0] = TAG_LBS;
		len = pack_tlv_data(ptr, aucTag, pstMsg->aucLBS, strlen((char *)pstMsg->aucLBS));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->aucSignal[0]){
		aucTag[0] = TAG_SIGNAL_VAL;
		len = pack_tlv_data(ptr, aucTag, pstMsg->aucSignal, strlen((char *)pstMsg->aucSignal));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->usVoltage){
		aucTag[0] = TAG_VOLTAGE;
		len = pack_tlv_data(ptr, aucTag, (unsigned char *)&pstMsg->usVoltage, sizeof(unsigned short));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->usLight){
		aucTag[0] = TAG_LIGHT;
		len = pack_tlv_data(ptr, aucTag, (unsigned char *)&pstMsg->usLight, sizeof(unsigned short));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->usSound){
		aucTag[0] = TAG_SOUND;
		len = pack_tlv_data(ptr, aucTag, (unsigned char *)&pstMsg->usSound, sizeof(unsigned short));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->iTemp){
		aucTag[0] = TAG_TEMPERATURE;
		len = pack_tlv_data(ptr, aucTag, (unsigned char *)&pstMsg->iTemp, sizeof(unsigned short));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	if(0 != pstMsg->usHumi){
		aucTag[0] = TAG_HUMIDITY;
		len = pack_tlv_data(ptr, aucTag, (unsigned char *)&pstMsg->usHumi, sizeof(unsigned short));
		if (len < 0){
			return -1;
		}
		usDLen += len;
		ptr += len;
	}
	
	aucTag[0] = TAG_LED;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->ucLED, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_SW1;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->ucSwitch1, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_SW2;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->ucSwitch2, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	pstMsg->aucMsgData[0] = usDLen>>8;
	pstMsg->aucMsgData[1] = usDLen&0xFF;
	
	pstMsg->usMsgLen = (usDLen+MSG_HEAD_LEN_SZ);
	return pstMsg->usMsgLen;
}

int pack_ack_message(Message *pstMsg)
{
	int len = 0;
	unsigned short usDLen = 0;
	unsigned char *ptr = pstMsg->aucMsgData;
	unsigned char aucTag[2] = {0};
	
	pstMsg->usMsgLen = 0;
	
	ptr += MSG_HEAD_LEN_SZ;
	
	aucTag[0] = TAG_IMEI;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucIMEI, strlen((char *)pstMsg->aucIMEI));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_ACK;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->ucACK, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	pstMsg->aucMsgData[0] = usDLen>>8;
	pstMsg->aucMsgData[1] = usDLen&0xFF;
	
	pstMsg->usMsgLen = (usDLen+MSG_HEAD_LEN_SZ);
	return pstMsg->usMsgLen;
}

int pack_heartbeat_message(Message *pstMsg)
{
	int len = 0;
	unsigned short usDLen = 0;
	unsigned char *ptr = pstMsg->aucMsgData;
	unsigned char aucTag[2] = {0};
	
	pstMsg->usMsgLen = 0;
	
	ptr += MSG_HEAD_LEN_SZ;
	
	aucTag[0] = TAG_IMEI;
	len = pack_tlv_data(ptr, aucTag, pstMsg->aucIMEI, strlen((char *)pstMsg->aucIMEI));
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	aucTag[0] = TAG_HEARTBEAT;
	len = pack_tlv_data(ptr, aucTag, &pstMsg->ucHeartbeat, 1);
	if (len < 0){
		return -1;
	}
	usDLen += len;
	ptr += len;
	
	pstMsg->aucMsgData[0] = usDLen>>8;
	pstMsg->aucMsgData[1] = usDLen&0xFF;
	
	pstMsg->usMsgLen = (usDLen+MSG_HEAD_LEN_SZ);
	return pstMsg->usMsgLen;
}

int pack_huawei_senser_info_msg(Message *pstMsg)
{
	//----------00/4RSRP/1ECL/4SNR/4CellID/2dy/4wd/2sd/2zy/2gq/1led/1sw1/1sw2
	//AT+NMGS=29,00FFFFFCE1010000001008F651530F6D00000A591936077000B8000000
	int iRet = 0;
	unsigned char ucSignalVal = 0;
	ucSignalVal = (unsigned char)atoi((char *)pstMsg->aucSignal);
	memset(pstMsg->aucMsgData, 0, sizeof(pstMsg->aucMsgData));
	iRet = snprintf((char *)pstMsg->aucMsgData, sizeof(pstMsg->aucMsgData), "00%08X%02X%08X%08X%02X%04X%08X%04X%04X%04X%02X%02X%02X",
																										 pstMsg->iRSRP,
																										 pstMsg->ucECL,
																										 pstMsg->iSNR,
																										 pstMsg->iCellID,
																										 ucSignalVal,
	
																										 pstMsg->usVoltage,
	                                                   pstMsg->iTemp,
																										 pstMsg->usHumi,
																										 pstMsg->usSound,
																										 pstMsg->usLight,
	                                                   
																										 pstMsg->ucLED,pstMsg->ucSwitch1,pstMsg->ucSwitch2);
	pstMsg->usMsgLen = iRet;
	return iRet;
}

int pack_huawei_ctl_ack_msg(Message *pstMsg)
{
	//----------00/2sd/2wd/1zy/2gq/2dy/1kg
	//AT+NMGS=11,00160003FF30101211CD00
	int iRet = 0;
	unsigned char ucCtlSta = 0;
	if(1 == pstMsg->ucLED){
		ucCtlSta |= 0x01;
	}
	if(1 == pstMsg->ucSwitch1){
		ucCtlSta |= 0x02;
	}
	if(1 == pstMsg->ucSwitch2){
		ucCtlSta |= 0x04;
	}
	memset(pstMsg->aucMsgData, 0, sizeof(pstMsg->aucMsgData));
	iRet = snprintf((char *)pstMsg->aucMsgData, sizeof(pstMsg->aucMsgData), "02%02X%02X%02X%02X", pstMsg->ucACK, ucCtlSta, pstMsg->aucMsgID[0], pstMsg->aucMsgID[1]);
	//printf("snprintf ret:%d\n", iRet);
	//iRet = strlen(pcOut);
	pstMsg->usMsgLen = iRet;
	return iRet;
}

static TlvData s_astUserTlv[MAX_TLV_TAG_SZ];
static unsigned char s_aucCmdData[128] = {0};
//001A040F383637373236303331363737343937CA0101A10101A20101
int parse_msg(Message *pstMsg)
{
	int ret = 0, i = 0, iCnt = 0;
	unsigned short usTag = 0;
	pTlvData tlv = s_astUserTlv;
	
	_vdStr2HexStr((char *)pstMsg->aucMsgData, s_aucCmdData, (int *)&pstMsg->usRevLen);
	if(2 > pstMsg->usRevLen) return -1;

	iCnt = unpack_tlv_data(tlv, &s_aucCmdData[MSG_HEAD_LEN_SZ], pstMsg->usRevLen-MSG_HEAD_LEN_SZ);

	for (i=0; i<iCnt; ++i){
    if(2 < tlv[i].tag.size){
			ret = 1; break;
		}
		if(tlv[i].val.size > 32){
      ret = 1; break;
    }
		_ByteToInt(tlv[i].tag.data, tlv[i].tag.size, (int *)&usTag);
		printf("TAG [%02X][%d][%02X]\n", usTag, tlv[i].val.size, tlv[i].val.data[0]);
		switch(usTag){
      case TAG_ACK://tlv[i].val.data, tlv[i].val.size
				pstMsg->ucACK = tlv[i].val.data[0];
				break;
			case TAG_ACTIVE:
				pstMsg->ucActive = tlv[i].val.data[0];
				break;
			case TAG_HOST_ADDR:
				break;
			case TAG_CMD:
				pstMsg->ucCmd = tlv[i].val.data[0];
				break;
			case TAG_CMD_VAL:
				pstMsg->ucCmdVal = tlv[i].val.data[0];
				break;
			case TAG_CMD_MSG:
				if(tlv[i].val.size > 16){
					tlv[i].val.size = 16;
				}
				memcpy(pstMsg->aucCmdMsg, tlv[i].val.data, tlv[i].val.size);
				break;
		}
	}
	return ret;
}

//+NNMI:4,AAAA000 -- ACK
//+NNMI:5,0131320001 -- CTL Cmd
int parse_coap_msg(Message *pstMsg)
{
	int ret = 0;
	
	_vdStr2HexStr((char *)pstMsg->aucMsgData, s_aucCmdData, (int *)&pstMsg->usRevLen);
	if(2 > pstMsg->usRevLen) return -1;
	pstMsg->ucCmd = 0;
	if(4 == pstMsg->usRevLen && 0xAA == s_aucCmdData[0]){
		pstMsg->ucCmd = MSG_ACK;
	}else if(0x01 == s_aucCmdData[0]){
		pstMsg->ucCmd = s_aucCmdData[1];
		pstMsg->ucCmdVal = s_aucCmdData[2];
		memcpy(pstMsg->aucMsgID, &s_aucCmdData[3], 2);
		if(CTL_LCD == pstMsg->ucCmd && 5 < pstMsg->usRevLen){
			memcpy(pstMsg->aucCmdMsg, &s_aucCmdData[5], pstMsg->usRevLen-5);
		}
	}else{
		ret = -2;
	}
	return ret;
}
